package ru.chaykin.rendering;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

import ru.chaykin.graphdrawers.Pen;
import ru.chaykin.load.parse.MIFParser;
import ru.chaykin.primitives.Circle;
import ru.chaykin.quadtree.QuadTree;
import ru.chaykin.viewobject.ViewObject;
import ru.chaykin.viewobject.geometry.Geometry;
import android.util.Log;


public class CullingDataThread extends CullingThread {
	
	public static final short GEO_BUFF_SIZE = 2048;
	
	public static volatile ViewObject[] geoBuff = new ViewObject[GEO_BUFF_SIZE];
	
	private static int objIndex = 0;
	
	public void run() {
		Log.d(getClass().getName(), "Thread started");
		tree = new QuadTree(MIFParser.getQuadElement());
		boolean isnNull = false;
		while (isActive) {	//Ищем и "переискиваем" (т.к. область отображения меняется пользователем)
			for (int j = 0; j < GEO_BUFF_SIZE; j++) {	//Перебираем объекты в буфере...
				
				synchronized(geoBuff) {// Вынесено отдельно и добавлена isnNull для минимизации времени в мониторе
					if (geoBuff[j] != null) {	//В буфере уже что-то есть...
						isnNull = true;
						bCircle = geoBuff[j].getBoundCircle();
					} else {
						isnNull = false;
					}
				}
				
				if (isnNull) { //В буфере уже что-то есть...
					if (!bCircle.in(ra))  //Объект больше не попадает в область видимости 
						fillVBuff(j); //Читаем новый из файла
				}
				else 
					fillVBuff(j); //Читаем новый объект из файла
			}	
		}
		Log.d(getClass().getName(), "Thread stoped");
	}
	
	/**
	 * Заполняет буфер для отображения объектом из отображенного на память файла
	 * @param index	- индекс, по которому заполняется буфер
	 */
	private final void fillVBuff(int index) {
		if (foundObjs.size() > 0) {
			if (objIndex >= foundObjs.size())
				objIndex = 0;
			float[] obj = foundObjs.get(objIndex);
			objIndex++;
			int listId = (int) obj[6]; //Получаем уникальный идентификатор объекта из списка найденных объектов
			bCircle = new Circle(obj[0], obj[1], obj[2]);
			Pen pen = new Pen(obj[3], 0, (int) obj[5]);
			byte[] btmp = getDataFromMappedBuff(listId, (int) obj[7]);
			ByteBuffer byteBuf = ByteBuffer.allocateDirect((int) obj[7]);
			byteBuf.order(ByteOrder.nativeOrder());
			synchronized(geoBuff) {
				FloatBuffer tmpBuff = byteBuf.asFloatBuffer();
				tmpBuff.put(ByteBuffer.wrap(btmp).asFloatBuffer());	//Записали в наш буффер для отображения объект
				geoBuff[index] = new Geometry(bCircle, pen, (int) obj[5], tmpBuff);
				geoBuff[index].setId(listId); //Установим уникальный идентификатор
			}
			return;
		}
	}

	private final byte[] getDataFromMappedBuff(int offset, int length) {
		int prevPos;
		byte[] btmp = new byte[length];
		synchronized(MIFParser.mappedDataByteBuff) {
			prevPos = MIFParser.mappedDataByteBuff.position();	//Сохраняем позицию файла (не забываем восстановить потом, чтобы запись в файл пошла по правильному индексу)
			MIFParser.mappedDataByteBuff.position(offset); //Установим позицию, чтобы прочитать наш объект
			MIFParser.mappedDataByteBuff.get(btmp, 0, length);
			MIFParser.mappedDataByteBuff.position(prevPos);	//Восстановили позицию файла
		}
		return btmp;
	}
}
